<?php
/**
 * Db_Object information expert
 * Helps to find  relations between objects
 * @author Kirill A Egorov kirill.a.egorov@gmail.com 
 * @copyright Copyright (C) 2011-2012  Kirill A Egorov, 
 * DVelum project http://code.google.com/p/dvelum/ , http://dvelum.net
 * @license General Public License version 3
 */
class Db_Object_Expert
{	
	static protected $_objectAssociations = null;
	
	static protected function _buildAssociations(){
		$objects = Db_Object_Manager::getRegisteredObjects();
		foreach ($objects as $name){
			$config = Db_Object_Config::getInstance($name);
			$links = $config->getLinks();
			self::$_objectAssociations[$name] = $links;
		}
	}
	/**
	 * Get Associated objects
	 * @param Db_Object $object
	 * @return array   like
	 * array(
	 * 	  'single' => array(
	 * 			'objectName'=>array(id1,id2,id3),
	 * 			...
	 * 			'objectNameN'=>array(id1,id2,id3),
	 * 	   ),
	 * 	   'multy' =>array(
	 * 			'objectName'=>array(id1,id2,id3),
	 * 			...
	 * 			'objectNameN'=>array(id1,id2,id3),
	 * 	   )
	 * )
	 */
	static public function getAssociated(Db_Object $object)
	{
		$linkedObjects = array('single'=>array(),'multy'=>array());
		
		if(is_null(self::$_objectAssociations))
			self::_buildAssociations();

		$objectName = $object->getName();
		$objectId = $object->getId();
		
		if(!isset(self::$_objectAssociations[$objectName]))
			return array();
			
		foreach (self::$_objectAssociations as $testObject=>$links)
		{
			if(!isset($links[$objectName]))
				continue;
			 	
			$sLinks = self::_getSingleLinks($objectId , $testObject , $links[$objectName]);
			 
			 if(!empty($sLinks))
			 	$linkedObjects['single'][$testObject] = $sLinks;		 
		}	
		
		$linkedObjects['multy'] = self::_getMultyLinks($objectName, $objectId);
		
		return $linkedObjects;	
	}
	/**
	 * Get "single link" associations
	 * when object has link as own property
	 * @param integer $objectId
	 * @param string $relatedObject - related object name
	 * @param array $links - links config like 
	 * 	array(
	 * 		'field1'=>'object',
	 * 		'field2'=>'multy'
	 * 		...
	 * 		'fieldN'=>'object',
	 *  )
	 *  @return array
	 */
	static protected function _getSingleLinks($objectId, $relatedObject , $links)
	{
		$relatedConfig = Db_Object_Config::getInstance($relatedObject);
		$fields = array();
		$singleRelated = array();
		foreach($links as $field=>$type)
		{
			if($type!=='object')
				continue;
				
			$fields[] = $field;
		}
		
		if(empty($fields))
			return  array();
			
			$db = Db_Object::getDbConnection();
			$sql = $db->select()->from($relatedConfig->getTable() , array('id'));
			foreach ($fields as $field)
				$sql->orWhere($db->quoteIdentifier($field).' =?' , $objectId);
				
			$data = $db->fetchAll($sql);
			
			if(empty($data))
				return array();
				
			return Utils::fetchCol('id', $data);	
	}
	/**
	 * Get multylink associations
	 * when links stored  in external objects
	 * @param string $objectName
	 * @param integer $objectId
	 * @return array
	 */
	static protected function _getMultyLinks($objectName , $objectId)
	{
		$db = Db_Object::getDbConnection();
		$linkTable = Db_Object_Config::getInstance(Db_Object::getLinksObject())->getTable();
		
		$sql = $db->select()
				  ->from($linkTable, array('id'=>'src_id','object'=>'src'))
				  ->where('`target` =?',$objectName)
				  ->where('`target_id` =?', $objectId);
		$multyLinks = $db->fetchAll($sql);	  
		
		$data = array();
		
		if(empty($multyLinks))
			foreach ($multyLinks as $record)
				$data[$record['object']][] = $record['id'];
		
		return $data;	
	}
}